/*
	msgMBoxCreate() causes EVENT_MSGQCREATE
	msgMBoxDestroy() causes EVENT_MSGQDELETE
	msgMBoxSend() causes EVENT_MSGQSEND
	msgMBoxReceive() causes EVENT_MSGQRECEIVE
*/

#include "vxWorks.h"
#include "stdlib.h"
#include "string.h"
#include "taskLib.h"
#include "smObjLib.h"
#include "errnoLib.h"
#include "intLib.h"
#include "eventLib.h"
#include "unistd.h"
#include "time.h"
#include "stdio.h"
#include "objLib.h"
#include "wdLib.h"
#include "msgQLib.h"
#include "private/distObjTypeP.h"

typedef int s32;
typedef unsigned int u32;
typedef unsigned char u8;

#define sleep(timeO) taskDelay (timeO * (sysClkRateGet())) /* macro */


#define MAX_Q_MSGS 10
#define MAX_Q_LENGTH 512

MSG_Q_ID msg_q_id;

#define STK_SIZE 5000  
#define SEND_PRORITY 102
#define PRODUCE_PRORITY 103
#define RECV_PRORITY 202
#define OPTIONS 0

//#define STACK
#define SELF_PACKET 1

#define STR 0

enum EMSGQ
{
    EMSGQ_DIST_NOT_INITIALIZED=0,
    EMSGQ_SMOBJ_NOT_INITIALIZED,
    EMSGQ_OBJ_ID_ERROR,
    EMSGQ_OBJ_DELETED,
    EMSGQ_OBJ_UNAVAILABLE,
    EMSGQ_OBJ_TIMEOUT,
    EMSGQ_INVALID_MSG_LENGTH,
    EMSGQ_NON_ZERO_TIMEOUT_AT_INT_LEVEL,
    EMSGQ_NOT_EVENTSEND_FAILED,
    EMSGQ_NOT_ISR_CALLABLE,
};

u32 msg_q_send(MSG_Q_ID msg_q_id, char *data, u32 len)
{
    u32 err =0;
    err = msgQSend(msg_q_id,data,len,WAIT_FOREVER, MSG_PRI_NORMAL);
    switch(err)
    {
        case OK:
            break;
        case S_distLib_NOT_INITIALIZED:
            err = EMSGQ_DIST_NOT_INITIALIZED;
            break;
        case S_smObjLib_NOT_INITIALIZED:
            err = EMSGQ_SMOBJ_NOT_INITIALIZED;
            break;
        case S_objLib_OBJ_ID_ERROR:
            err = EMSGQ_OBJ_ID_ERROR;
            break;
        case S_objLib_OBJ_DELETED:
            err = EMSGQ_OBJ_DELETED;
            break;
        case S_objLib_OBJ_UNAVAILABLE:
            err = EMSGQ_OBJ_UNAVAILABLE;
            break;
        case S_objLib_OBJ_TIMEOUT:
            err = EMSGQ_OBJ_TIMEOUT;
            break;
        case S_msgQLib_INVALID_MSG_LENGTH:
            err = EMSGQ_INVALID_MSG_LENGTH;
            break;
        case S_msgQLib_NON_ZERO_TIMEOUT_AT_INT_LEVEL:
            err = EMSGQ_NON_ZERO_TIMEOUT_AT_INT_LEVEL;
            break;    
        case S_eventLib_EVENTSEND_FAILED:
            err = EMSGQ_NOT_EVENTSEND_FAILED;
            break;
        default:
            printf("msgQSend ERR %d\n", err);
            break;
    }
    return err;
}

STATUS msg_q_recv(MSG_Q_ID msg_q_id, char *msg, u32 *err)
{
    u32 msg_ret=0;
    msg_ret = msgQReceive(msg_q_id, msg, MAX_Q_LENGTH, WAIT_FOREVER);
    switch(msg_ret)
    {
        case S_distLib_NOT_INITIALIZED:
            *err = EMSGQ_DIST_NOT_INITIALIZED;
            break;
        case S_smObjLib_NOT_INITIALIZED:
            *err = EMSGQ_SMOBJ_NOT_INITIALIZED;
            break;    
        case S_objLib_OBJ_ID_ERROR:
            *err = EMSGQ_OBJ_ID_ERROR;
            break;
        case S_objLib_OBJ_DELETED:
            *err = EMSGQ_OBJ_DELETED;
            break;
        case S_objLib_OBJ_UNAVAILABLE:
            *err = EMSGQ_OBJ_UNAVAILABLE;
            break;    
        case S_objLib_OBJ_TIMEOUT:
            *err = EMSGQ_OBJ_TIMEOUT;
            break;
        case S_msgQLib_INVALID_MSG_LENGTH:
            *err = EMSGQ_INVALID_MSG_LENGTH;
            break;
        case S_intLib_NOT_ISR_CALLABLE:
            *err = EMSGQ_NOT_ISR_CALLABLE;
            break;
        default:
            printf("msgQReceive bytes %d\n", msg_ret);
            break;
    }
    return msg_ret;
}

#if SELF_PACKET
void task_msgQ_send(void)
{
    u32 err=0;
    char data[]="welcome queue message\n";   
    u32 val=0x30;
    FOREVER
    {    
  #if STR
       msg_q_send(msg_q_id,data, sizeof(data));
       printf("send %s\n", data);
  #else 
       msg_q_send(msg_q_id,(char *)&val, sizeof(u32));
       printf("send %x\n", val);
  #endif     
       sleep(3);
    }
}
#else
void task_msgQ_send(void)
{
    u32 err=0;
    char data[]="welcome queue message\n";   
    u32 val=0x30;
    FOREVER
    {    
  #if STR
       msgQSend(msg_q_id, data, sizeof(data),WAIT_FOREVER, MSG_PRI_NORMAL);
       printf("send %s\n", data);
  #else 
       msgQSend(msg_q_id, &val, sizeof(u32),WAIT_FOREVER, MSG_PRI_NORMAL);
       printf("send %x\n", val);
  #endif     
       sleep(3);
    }
}

#endif

void task_msgQ_producer(void)
{
    u32 err=0;
    char data[]="producer queue message\n";   
    u32 val=0x10;
    FOREVER
    {    
  #if STR
       msg_q_send(msg_q_id,data, sizeof(data));
       printf("send %s\n", data);
  #else 
       msg_q_send(msg_q_id,(char *)&val, sizeof(u32));
       printf("send %x\n", val);
  #endif     
       sleep(5);
    }
}

#if SELF_PACKET
void task_msgQ_recv(void)
{
    u32 err=0;
#ifdef STACK 
    char recv[MAX_Q_LENGTH]={0};
#endif   
     FOREVER
     {
       #ifndef STACK
          char *recv=(char *)calloc(1, sizeof(char)*MAX_Q_LENGTH);
          if(NULL == recv)
            break; 
       #endif     
          msg_q_recv(msg_q_id,recv,&err); 
          {
 #if STR         
            printf("recv %s\n", recv);
 #else
            printf("recv %x\n", *recv);
 #endif           
          }
        #ifndef STACK   
        cfree(recv);
        #endif
          sleep(3);
     }
 
}

#else
void task_msgQ_recv(void)
{
    u32 err=0;
#ifdef STACK 
    char recv[MAX_Q_LENGTH]={0};
#endif
     FOREVER
     {
    #ifndef STACK  
        char *recv=(char *)calloc(1, sizeof(char)*MAX_Q_LENGTH);
         if(NULL == recv)
            break;     
      #endif      
          err = msgQReceive(msg_q_id, recv, MAX_Q_LENGTH, WAIT_FOREVER);
          printf("recv bytes %d\n", err);
          {
 #if STR         
            printf("recv %s\n", recv);
 #else
            printf("recv %x\n", *recv);
 #endif           
          }
     #ifndef STACK   
        cfree(recv);
        #endif
          sleep(3);
     }
 
}

#endif
void msgQ_init()
{ 
   msg_q_id =  msgQCreate(MAX_Q_MSGS,MAX_Q_LENGTH,MSG_Q_FIFO);
   if(NULL == msg_q_id)
   {
        printf("msg queue create failed\n");
   }
}

s32 queue(void)
{
    u32 send_id;
    u32 product;
    u32 recv_id;
    msgQ_init();
    
    send_id = taskSpawn("send", SEND_PRORITY, OPTIONS, STK_SIZE,(FUNCPTR)task_msgQ_send,0,0,0,0,0,0,0,0,0,0);
    product = taskSpawn("producer", PRODUCE_PRORITY, OPTIONS, STK_SIZE,(FUNCPTR)task_msgQ_producer,0,0,0,0,0,0,0,0,0,0);
    recv_id = taskSpawn("recv", RECV_PRORITY, OPTIONS, STK_SIZE,(FUNCPTR)task_msgQ_recv,0,0,0,0,0,0,0,0,0,0);
    printf("send task id %x, %x\t recv task id %x\n", send_id, product, recv_id);
    return 0;
}


